/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.etrs.formathlon.persistance.utilisateur;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Stateless;
import javax.persistence.NoResultException;
import net.etrs.formathlon.entity.utilisateur.Utilisateur;
import net.etrs.formathlon.metier.exception.MetierException;
import net.etrs.formathlon.metier.service.EntiteManager;
import net.etrs.formathlon.metier.service.EntiteManager.NiveauHierarchique;
import net.etrs.formathlon.metier.utils.constantes.RoleSpring;
import net.etrs.formathlon.persistance.utils.AbstractFacade;
import net.etrs.formathlon.persistance.utils.JpaRequestNames;

/**
 * EJB Session lié à l'entité Utilisateur. pour tous ce qui concerne 
 * la persistance.
 * @author OPIF
 */
@Stateless
public class UtilisateurFacade extends AbstractFacade<Utilisateur> {

    /**
     * Retourne la liste des utilisateurs qui ont la même entité et plus
     * s'ils ont un personnel associés.
     * 
     * @param entite Le code de l'entité de la personne supérieure.
     * @param niveau 
     * @return la liste des subordonnés.
     */
    public List<Utilisateur> getSubordonnes(String entite, NiveauHierarchique niveau) throws MetierException {
        return getEm().createNamedQuery(JpaRequestNames.LISTE_SUBORDONNES).setParameter("entite", EntiteManager.getEntite(entite, niveau) + "%").getResultList();
    }

    /**
     * Retourne la liste des utilisateurs qui ont la même entité et plus
     * s'ils ont un personnel associés.
     * @param utilisateur Responsable de qui on souhaite avoir la liste des subordonnées.
     * @return list<Utilisateur> Liste des utilisateurs correspondants.
     */
    public List<Utilisateur> getSubordonnes(Utilisateur utilisateur) throws MetierException {
        NiveauHierarchique niveau = null;
        if (isInRole(utilisateur, RoleSpring.ROLE_CHEF_COURS)) {
            niveau = NiveauHierarchique.COURS;
        }
        if (isInRole(utilisateur, RoleSpring.ROLE_CHEF_DIV)) {
            niveau = NiveauHierarchique.DIVISION;
        }
        if (isInRole(utilisateur, RoleSpring.ROLE_CHEF_DIR)) {
            niveau = NiveauHierarchique.DIRECTION;
        }
        if (niveau != null) {
            return getSubordonnes(utilisateur.getEntite(), niveau);
        } else {
            List<Utilisateur> retour = new ArrayList<Utilisateur>();
            retour.add(utilisateur);
            return retour;
        }
    }

    /**
     * Recherche des supérieurs.
     * @param entite Le code de l'entité de la personne subordonnée.
     * @param niveau Le niveau des chefs/adjoints recherchés
     * @return la liste des supérieurs.
     */
    public List<Utilisateur> getSuperieurs(String entite, NiveauHierarchique niveau) throws MetierException {
        List<Utilisateur> tempListe = getEm().createNamedQuery(JpaRequestNames.LISTE_SUPERIEURS).setParameter("entite", EntiteManager.getEntite(entite, niveau) + "%").getResultList();
        List<Utilisateur> retourListe = new LinkedList<Utilisateur>();

        //On détermine le role recherché en fonction du niveau en paramètre
        RoleSpring roleRecherche = null;
        switch (niveau) {
            case DIRECTION:
                roleRecherche = RoleSpring.ROLE_CHEF_DIR;
                break;
            case DIVISION:
                roleRecherche = RoleSpring.ROLE_CHEF_DIV;
                break;
            case COURS:
                roleRecherche = RoleSpring.ROLE_CHEF_COURS;
                break;
        }

        // On regarde dans la liste des personnes qui font partie de la même entité
        // celle qui ont le droit sélectionné : ce sont les supérieurs.
        for (Utilisateur utilisateur : tempListe) {
            if (isInRole(utilisateur, roleRecherche)) {
                retourListe.add(utilisateur);
            }
        }
        return retourListe;
    }

    /**
     * Affirme qu'un utilisateur est (ou non) propriétaire du role passé
     * en paramètre.
     * @param utilisateur
     * @param role
     * @return Vrai si l'utilisateur est dans le role en paramètre
     */
    public boolean isInRole(Utilisateur utilisateur, RoleSpring role) {
        return utilisateur.getListRoleSpring().contains(role);
    }

    /**
     * Methode de recherche d'un utilisateur par rapport a son login.
     * @param a_Login 
     * @return l'utilisateur correspondant au login
     */
    public Utilisateur getUtilisateurByLogin(String a_Login) 
    {
        Logger.getLogger(UtilisateurFacade.class.getCanonicalName()).log(Level.INFO, null, String.format("Recherche de %s",a_Login));
        Utilisateur utilisateur = null;
        try {
            utilisateur = (Utilisateur) getEm().createNamedQuery(JpaRequestNames.GET_UTILISATEUR_BY_LOGIN).setParameter("logintest", a_Login).getSingleResult();

        } catch (NoResultException e) {
            Logger.getLogger(UtilisateurFacade.class.getCanonicalName()).log(Level.WARNING, null, "getUtilisateurByLogin Erreur user est null");
        }
        return utilisateur;
    }

    /**
     * Retourne la liste des utilisateurs qui on un personnel associé soit 
     * la liste complete des personnels.
     * @return List<Utilisateur>
     */
    public List<Utilisateur> getPersonnels() {
        return getEm().createNamedQuery(JpaRequestNames.LISTE_PERSONNEL).getResultList();
    }

    /**
     * Liste des divisions.
     * @return La liste de divisions
     * @throws MetierException 
     */
    public Set<String> getDistinctDivision() throws MetierException {
        List<String> listEntite = getEm().createNamedQuery(JpaRequestNames.LISTE_DISTINCT_ENTITE).getResultList();
        Set<String> retour = new HashSet<String>(listEntite.size());
        for (String entite : listEntite) {
            retour.add(EntiteManager.getSubEntite(entite, NiveauHierarchique.DIVISION));
        }
        return retour;
    }

    /**
     * Liste des cours d'une division.
     */
    public Set<String> getDistinctCours(String division) throws MetierException {
        List<String> listEntite = getEm().createNamedQuery(JpaRequestNames.LISTE_DISTINCT_ENTITE_DIVISION).setParameter("entite", "%" + division + "%").getResultList();
        Set<String> retour = new HashSet<String>(listEntite.size());
        for (String entite : listEntite) {
            retour.add(EntiteManager.getSubEntite(entite, NiveauHierarchique.COURS));
        }
        return retour;
    }

    /**
     * Si l'utilisateur est un personnel instructeur.
     * @param utilisateur
     * @return Vrai si l'utilisateur est instructeur
     */
    public boolean isInstructeur(Utilisateur utilisateur) {
        try {
               return !utilisateur.getPersonnel().getListSpecialite().isEmpty();
        } catch (NullPointerException ex) {
            //l'utilisateur n'a pas de personnel il ne peut donc pas etre un instructeur
             return false;
        }      
    }
}
